package com.eu.ebpm.engine.pvm;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import com.eu.ebpm.SpringContext;
import com.eu.ebpm.engine.cmd.Command;
import com.eu.ebpm.engine.entity.deploy.Mission;
import com.eu.ebpm.engine.entity.deploy.Transfer;
import com.eu.ebpm.engine.entity.runtime.TaskEntity;
import com.eu.ebpm.engine.exception.ErrorCode;
import com.eu.ebpm.engine.exception.WorkFlowException;
import com.eu.ebpm.engine.interceptor.Interceptor;
import org.springframework.util.StringUtils;

/**
 * 
 * 类名称: PvmEngine
 * 类描述: 流程虚拟机处理引擎,主要处理服务的调度分发
 * 
 * 	@流程规则：
 * 							1、子流程存在分支的情况下，允许单独执行。否则，子流程执行完毕以后，必须合并到父流程中。
 * 
 * @author 王晓华
 * @since 2015-1-20 下午03:04:04
 * @version v1.0
 */
public abstract class PvmEngine implements EngineService {
	
	@Autowired
	protected PvmContainer pvmContainer;
	
	protected Command<?> command;
	
	/**
	 * 服务调度
	 * @param task 执行任务
	 * @param transfers 任务执行方向
	 * @param vs 执行参数
	 */
	protected void doDispatch(TaskEntity task, List<Transfer> transfers, Map<String, Object> vs) {
		
		Mission next = matchedNextTransfer(transfers, vs).getToMission();
		
		pvmContainer.getPvmService(next.getType()).execute(next, task, vs);
		
	}
	
	public static Transfer matchedNextTransfer(List<Transfer> transfers, Map<String, Object> vs) {
		
		Transfer next = null;
		
		if(transfers.size() == 1) {
			
			next = transfers.get(0);
			
		} else {
			
			if(vs == null) {
				throw new WorkFlowException(ErrorCode.RU_VARIABLE_NULL);
			}
			
			int result = 0;
			for(Transfer t : transfers) {
				if(t.getExpressCondition().isMate(vs)) {
					next = t;
					result ++;
				}
			}
			
			if(result != 1) {
				throw new WorkFlowException(ErrorCode.RU_NOTFOUND_NEXTMISSION, String.format(" ==> 匹配个数:%d", result));
			}
			
		}
		
		return next;
	}

	public abstract void into(Mission mission, TaskEntity task, Map<String, Object> variables);

	/**
	 * 默认空的实现
	 */
	public void commit(Mission fromMission, TaskEntity task, Map<String, Object> variables) {}
	
	public void complete(Mission mission, TaskEntity task, Map<String, Object> variables) {
		List<Interceptor> interceptors = initInterceptors(mission.getFilters());
		if(interceptors != null) {
			for(Interceptor i : interceptors) {
				i.before(task, variables);
			}
		}
		this.commit(mission, task, variables);
		if(interceptors != null) {
			for(Interceptor i : interceptors) {
				i.after(task, variables);
			}
		}
	}
	

	public void execute(Mission mission, TaskEntity task, Map<String, Object> variables) {
		List<Interceptor> interceptors = initInterceptors(mission.getFilters());
		if(interceptors != null) {
			for(Interceptor i : interceptors) {
				i.before(task, variables);
			}
		}
		this.into(mission, task, variables);
		if(interceptors != null) {
			for(Interceptor i : interceptors) {
				i.after(task, variables);
			}
		}
	}
	

	/**
	 * 
	 * @param filterValue
	 * @return 拦截器列表
	 */
	private List<Interceptor> initInterceptors(String filterValue) {
		List<Interceptor> interceptors = null;
		if(!StringUtils.isEmpty(filterValue)) {
			interceptors = new ArrayList<Interceptor>();
			if(filterValue.indexOf(",") > 0) {
				String[] fs = filterValue.split(",");
				for(String f : fs) {
					interceptors.add(getInterceptor(f));
				}
			} else {
				interceptors.add(getInterceptor(filterValue));
			}
		}
		return interceptors;
	}

	private Interceptor getInterceptor(String interceptor) {
		Object obj = SpringContext.getBean(interceptor);
		if(obj == null) //判断过滤器是否为空
			throw new WorkFlowException(ErrorCode.RU_INTERCEPTOR_NOFOUND);
		if(!(obj instanceof Interceptor)) //判断是否为过滤器
			throw new WorkFlowException(ErrorCode.BEAN_TYPE_CHANGE_ERROR);
		return (Interceptor) obj;
	}
	
	
	
	
	

}
